<?php


namespace services\linkedcare;

use common\components\Service;
use common\helpers\CommonHelper;
use common\helpers\DateHelper;
use common\helpers\RedisHelper;
use common\models\linkedcare\LinkedcarePatients;
use common\models\linkedcare\LinkedcarePatientsFeeDetail;
use common\models\linkedcare\LinkedcarePatientsOrderDetail;
use common\models\linkedcare\LinkedcarePatientsRecord;
use common\models\patient\Patient;
use common\models\patient\PatientType;
use common\models\spoker\Spoker;
use services\patient\PatientOrderService;
use services\spoker\SpokerService;
use Yii;
use yii\db\Expression;

class LinkedcarePatientsFeeDetailService extends Service
{
    /**
     * 消费列表
     * @param array $params
     * @param int $page
     * @param int $pageSize
     * @return array
     */
    public function getListPage(array $params = [], int $page = 0, int $pageSize = 0): array
    {
        $query = LinkedcarePatientsFeeDetail::find()->alias('lpf')
            ->select([
                'lpf.payDateTime pay_time', 'lpf.actualPrice actual_price',
                'lp.officeName shop_name',
                'p.id', 'p.name', 'p.type_id', 'p.last_order_id',
            ])
            ->innerJoin(LinkedcarePatients::tableName().' lp', 'lp.linkcared_patient_id = lpf.linkcared_patient_id')
            ->innerJoin(Patient::tableName().' p', 'p.mobile = lp.mobile')
            ->where([
                'p.user_id' => Yii::$app->user->identity->member_id,
                'p.status' => Patient::STATUS_ENABLE
            ]);
        if (isset($params['name']) && $params['name']) {
            $query->andWhere(['like', 'p.name', $params['name']]);
        }
        // 排序
        $order = [
            'lpf.payDateTime' => SORT_DESC,
            'lpf.id' => SORT_DESC,
        ];

        return $this->getListPageRes($query, $page, $pageSize, $order);
    }

    /**
     * 格式化列表
     * @param array $data
     * @return array
     */
    public function getListPageFormat(array $data = []): array
    {
        // 最近一次预约记录
        $patientOrderMap = PatientOrderService::getPatientOrderMap(array_column($data, 'last_order_id'));
        $list = [];
        foreach ($data as $row) {
            $treatmentProjectId = $patientOrderMap[$row['id']]->treatment_project_id ?? 0;
            $treatmentProject = RedisHelper::getTreatmentProject($treatmentProjectId);
            $patientType = RedisHelper::getPatientType($row['type_id']);
            $list[] = [
                'id' => $row['id'],
                'name' => $row['name'],
                'shop_name' => $row['shop_name'],
                'actual_price' => $row['actual_price'],
                'treatment_project' => $treatmentProject ? $treatmentProject->name : '',
                'type_str' => $patientType && $patientType->status != PatientType::STATUS_DELETE ? $patientType->name : '',
                'pay_time_str' => DateHelper::timestampToDate(strtotime($row['pay_time']), DateHelper::DATE_FORMAT_4),
            ];
        }
        return $list;
    }

    /**
     * PC消费列表
     *
     * @param array $params
     * @param int $page
     * @param int $pageSize
     * @return array
     */
    public function feeList(array $params = [], int $page = 0, int $pageSize = 0): array
    {
        $query = LinkedcarePatientsFeeDetail::find()
            ->alias('lpf')
            ->select([
                'lpf.id', 'lpf.payDateTime pay_time', 'lpf.actualPrice actual_price',
                'lpf.doctorId doctor_id', 'lpf.doctorName doctor_name',
                'lp.officeName shop_name',
                'p.id patient_id', 'p.name', 'p.type_id', 'p.last_order_id', 'p.spoker_id',
                's.name spoker_name',
                'GROUP_CONCAT(lpo.itemName) item_name'
            ])
            ->leftJoin(LinkedcarePatientsOrderDetail::tableName() . ' lpo', 'lpo.chargeOrderId = lpf.chargeOrderId')
            ->innerJoin(LinkedcarePatients::tableName() . ' lp', 'lp.linkcared_patient_id = lpf.linkcared_patient_id')
            ->leftJoin(Patient::tableName() . ' p', 'p.mobile = lp.mobile')
            ->leftJoin(Spoker::tableName() . ' s', 'p.spoker_id = s.id')
            ->where([
                'p.status' => Patient::STATUS_ENABLE
            ])
            ->groupBy('lpf.id');
        // 开始时间
        if (isset($params['pay_time_stime']) && $params['pay_time_stime']) {
            $query->andWhere(['>=', 'lpf.payDateTime', date('Y-m-d H:i:s', strtotime($params['pay_time_stime']))]);
        }
        // 结束时间
        if (isset($params['pay_time_etime']) && $params['pay_time_etime']) {
            $query->andWhere(['<=', 'lpf.payDateTime', date('Y-m-d H:i:s', strtotime($params['pay_time_etime'] . ' 23:59:59'))]);
        }
        if (isset($params['keywords']) && $params['keywords']) {
            $query->andWhere(['like', 'p.name', $params['keywords']]);
        }
        if (isset($params['spoker_id']) && $params['spoker_id']) {
            $query->andWhere(['p.spoker_id' => $params['spoker_id']]);
        }
        // 排序
        $order = [
            'lpf.payDateTime' => SORT_DESC,
            'lpf.id' => SORT_DESC,
        ];

        $list = $this->getListPageRes($query, $page, $pageSize, $order);
        return $list;
    }

    /**
     * 统计用户患者消费额
     * @return int
     */
    public static function getUserConsumeMoney(array $params = []): string
    {
        $query = LinkedcarePatientsFeeDetail::find()->alias('lpf')
            /*->select([
                'lpf.payDateTime pay_time', 'lpf.actualPrice actual_price',
                'lp.officeName shop_name',
                'p.id', 'p.name', 'p.type_id', 'p.last_order_id',
            ])*/
            ->innerJoin(LinkedcarePatients::tableName().' lp', 'lp.linkcared_patient_id = lpf.linkcared_patient_id')
            ->innerJoin(Patient::tableName().' p', 'p.mobile = lp.mobile')
            ->where([
                'p.user_id' => Yii::$app->user->identity->member_id,
                'p.status' => Patient::STATUS_ENABLE
            ]);
        if (isset($params['patient_id']) && $params['patient_id']) {
            $query->andWhere(['p.id' => $params['patient_id']]);
        }
        if (isset($params['start_time']) && $params['start_time']) {
            $query->andWhere(['>=', 'lpf.payDateTime', $params['start_time']]);
        }
        if (isset($params['end_time']) && $params['end_time']) {
            $query->andWhere(['<=', 'lpf.payDateTime', $params['end_time'].' 23:59:59']);
        }
        $total = $query->sum('lpf.actualPrice');
        return number_format($total ?: 0, 2,'.', '');
    }

    /**
     * 获取患者新增月账单统计
     * @return array
     */
    public static function getMonthBillByUser(array $params): array
    {
        $query = Patient::find()->alias('p')
            ->select(['p.user_id', 'SUM(lpf.actualPrice) actual_price'])
            ->innerJoin(LinkedcarePatients::tableName().' lp', 'lp.mobile = p.mobile')
            ->innerJoin(LinkedcarePatientsFeeDetail::tableName().' lpf', 'lpf.linkcared_patient_id = lp.linkcared_patient_id')
            ->where([
                'p.status' => Patient::STATUS_ENABLE
            ])
            ->groupBy('p.user_id');
        if (isset($params['start_time']) && $params['start_time']) {
            $query->andWhere(['>=', 'lpf.payDateTime', $params['start_time']]);
        }
        if (isset($params['end_time']) && $params['end_time']) {
            $query->andWhere(['<=', 'lpf.payDateTime', $params['end_time'].' 23:59:59']);
        }
        return $query->having(['>', 'actual_price', 0])->indexBy('user_id')->asArray()->all();
    }

    /**
     * 统计消费数排行榜
     * @return array
     */
    public static function getRankList(array $params = []): array
    {
        $query = Patient::find()->alias('p')
            ->select(['p.spoker_id', 'SUM(lpf.actualPrice) actual_price', 'MAX(lpf.payDateTime) pay_date_time'])
            ->innerJoin(LinkedcarePatients::tableName().' lp', 'lp.mobile = p.mobile')
            ->innerJoin(LinkedcarePatientsFeeDetail::tableName().' lpf', 'lpf.linkcared_patient_id = lp.linkcared_patient_id')
            ->where([
                'p.status' => Patient::STATUS_ENABLE
            ])
            ->groupBy('p.spoker_id');
        if (isset($params['start_time']) && $params['start_time']) {
            $query->andWhere(['>=', 'lpf.payDateTime', $params['start_time']]);
        }
        if (isset($params['end_time']) && $params['end_time']) {
            $query->andWhere(['<=', 'lpf.payDateTime', $params['end_time'].' 23:59:59']);
        }
        $list = $query
            ->orderBy([
                'actual_price' => SORT_DESC,
                'pay_date_time' => SORT_ASC,
            ])
            ->limit(10)
            ->asArray()
            ->all();
        // 代言人集合
        $spokerMap = SpokerService::getMapByIds(array_column($list, 'spoker_id'));
        $listFormat = [];
        foreach ($list as $row) {
            $listFormat[] = [
                'spoker_id' => $row['spoker_id'],
                'actual_price' => $row['actual_price'],
                'name' => CommonHelper::getRankNameStr($spokerMap[$row['spoker_id']]->name ?? ''),
            ];
        }
        return $listFormat;
    }

    /**
     * 患者详情消费预约query
     * @param int $patientId
     * @return \yii\db\ActiveQuery
     */
    public static function getPatientConsumeDetailQuery(int $patientId)
    {
        $query = LinkedcarePatientsFeeDetail::find()->alias('lpf')
            ->select([
                'lpf.id',
                'unix_timestamp(lpf.payDateTime) sort_time',
                new Expression("1 type")
            ])
            ->innerJoin(LinkedcarePatients::tableName().' lp', 'lp.linkcared_patient_id = lpf.linkcared_patient_id')
            ->innerJoin(Patient::tableName().' p', 'p.mobile = lp.mobile')
            ->where([
                'p.id' => $patientId,
            ]);
        return $query;
    }

    /**
     * 患者详情预约记录
     * @param int|array $ids
     * @return array
     */
    public static function getPatientDetailConsumeMap(int|array $ids): array
    {
        $query = LinkedcarePatientsFeeDetail::find()->alias('lpf')
            ->select([
                'lpf.id', 'lpf.payDateTime', 'lpf.actualPrice actual_price', 'lpf.chargeOrderId',
                'lp.officeName shop_name',
//                'lpr.consultantName consultant_name', 'lpr.doctorName doctor_name',
            ])
            ->innerJoin(LinkedcarePatients::tableName().' lp', 'lp.linkcared_patient_id = lpf.linkcared_patient_id')
//            ->innerJoin(LinkedcarePatientsRecord::tableName().' lpr', 'lpr.chargeOrderId = lpf.chargeOrderId')
//            ->innerJoin(Patient::tableName().' p', 'p.mobile = lp.mobile')
            ->where([
                'lpf.id' => $ids,
            ]);
        $data = $query->asArray()->all();
        // 治疗项目
        $orderMap = LinkedcarePatientsOrderDetailService::getFeeListMap(array_column($data, 'chargeOrderId'));
        $dataFormat = [];
        foreach ($data as $row) {
            $order = $orderMap[$row['chargeOrderId']] ?? [];
            $dataFormat[$row['id']] = [
                'treatment_project' => $order ? array_column($order, 'itemName') : [],
                'actual_price' => $row['actual_price'],
                'shop_name' => $row['shop_name'],
                'consultant_name' => $order[0]['consultantName'] ?? '',// 咨询和医生取治疗项目第一条记录
                'doctor_name' => $order[0]['doctorName'] ?? '',
                'created_at_str' => DateHelper::timestampToDate(strtotime($row['payDateTime']), DateHelper::DATE_FORMAT_4),
            ];
        }
        return $dataFormat;
    }
}
